import frappe
from frappe.utils import password

def apply_password_patches():
    """应用密码相关的达梦数据库补丁"""
    
    # 保存原始函数
    original_set_encrypted_password = password.set_encrypted_password
    original_update_password = password.update_password

    def patched_set_encrypted_password(doctype, name, pwd, fieldname="password"):
        """设置加密密码，支持达梦数据库
        
        Args:
            doctype: 文档类型
            name: 文档名称
            pwd: 密码
            fieldname: 字段名称
        """
        if frappe.conf.db_type != "dm":
            return original_set_encrypted_password(doctype, name, pwd, fieldname)

        try:
            # 达梦数据库使用 MERGE INTO 语句
            frappe.db.sql(
                """
                MERGE INTO "__Auth" T1
                USING (SELECT %(doctype)s AS "doctype", %(name)s AS "name", %(fieldname)s AS "fieldname") T2
                ON (T1."doctype" = T2."doctype" AND T1."name" = T2."name" AND T1."fieldname" = T2."fieldname")
                WHEN MATCHED THEN
                    UPDATE SET "password" = %(pwd)s
                WHEN NOT MATCHED THEN
                    INSERT ("doctype", "name", "fieldname", "password", "encrypted")
                    VALUES (%(doctype)s, %(name)s, %(fieldname)s, %(pwd)s, 1)
                """,
                {
                    "doctype": doctype,
                    "name": name,
                    "fieldname": fieldname,
                    "pwd": password.encrypt(pwd)
                }
            )

        except frappe.db.DataError as e:
            if frappe.db.is_data_too_long(e):
                frappe.throw(frappe._("Most probably your password is too long."), exc=e)
            raise e

    def patched_update_password(user, pwd, doctype="User", fieldname="password", logout_all_sessions=False):
        """更新用户密码，支持达梦数据库
        
        Args:
            user: 用户名
            pwd: 新密码
            doctype: 文档类型
            fieldname: 字段名称
            logout_all_sessions: 是否登出所有会话
        """
        if frappe.conf.db_type != "dm":
            return original_update_password(user, pwd, doctype, fieldname, logout_all_sessions)

        # 使用 passlib 加密密码
        hashPwd = password.passlibctx.hash(pwd)

        # 达梦数据库使用 MERGE INTO 语句
        frappe.db.sql(
            """
            MERGE INTO "__Auth" T1
            USING (SELECT %(doctype)s AS "doctype", %(name)s AS "name", %(fieldname)s AS "fieldname") T2
            ON (T1."doctype" = T2."doctype" AND T1."name" = T2."name" AND T1."fieldname" = T2."fieldname")
            WHEN MATCHED THEN
                UPDATE SET 
                    "password" = %(pwd)s,
                    "encrypted" = 0
            WHEN NOT MATCHED THEN
                INSERT ("doctype", "name", "fieldname", "password", "encrypted")
                VALUES (%(doctype)s, %(name)s, %(fieldname)s, %(pwd)s, 0)
            """,
            {
                "doctype": doctype,
                "name": user,
                "fieldname": fieldname,
                "pwd": hashPwd
            }
        )

        # 清除所有会话（除了当前会话）
        if logout_all_sessions:
            from frappe.sessions import clear_sessions
            clear_sessions(user=user, keep_current=True, force=True)

    # 应用补丁
    password.set_encrypted_password = patched_set_encrypted_password
    password.update_password = patched_update_password
